package com.oocl.im.server;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.oocl.im.pojo.MsgPackage;
import com.oocl.im.pojo.Operation;

class Handler implements Runnable {
	private String name;
	private Socket socket;
	private ObjectInputStream in;
	private ObjectOutputStream out;
	private HashMap<String, Handler> handlerPool;

	public Handler(String name, Socket socket, ObjectInputStream in, ObjectOutputStream out,
			HashMap<String, Handler> handlerPool) throws Exception {
		super();
		this.name = name;
		this.socket = socket;
		this.in = in;
		this.out = out;
		this.handlerPool = handlerPool;
	}

	@Override
	public void run() {
		MsgPackage msg = null;
		try {
			notify2();
			while (true) {
				msg = (MsgPackage) in.readObject();
				switch (msg.getOpeartion()) {
				case CHAT:
					chat(msg);
					break;
				case SHAKE:
					shake(msg);
					break;
				case EXIT:
					exit(msg);
					return;
				default:
					break;
				}
			}

		} catch (SocketException E) {
			synchronized (handlerPool) {
				handlerPool.put(name, null);
			}
			try {
				notify2();
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(name + " exit");
		} catch (Exception e) {
			e.printStackTrace();
			synchronized (handlerPool) {
				handlerPool.put(name, null);
			}
			try {
				notify2();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

	public void exit(MsgPackage msg) throws Exception {
		String sender = msg.getSender();
		System.out.println(sender + " exit");
		synchronized (handlerPool) {
			handlerPool.put(sender, null);
		}
		notify2();
	}

	public void shake(MsgPackage msg) throws Exception {
		String receiver = msg.getReceiver();
		if (msg.getReceiver().equals("all")) {
			System.out.println("cannot shake all people");
		} else {
			synchronized (handlerPool) {
				Handler h = handlerPool.get(receiver);
				if (h != null) {
					h.out.writeObject(msg);
				}
			}
		}
	}

	public void chat(MsgPackage msg) throws Exception {
		String sender = msg.getSender();
		String receiver = msg.getReceiver();
		if ("all".equals(receiver)) {
			synchronized (handlerPool) {
				for (Map.Entry<String, Handler> entry : handlerPool.entrySet()) {
					boolean on = entry.getValue() != null;
					boolean isSelf = entry.getKey().equals(sender);
					if (on && !isSelf) {
						entry.getValue().out.writeObject(msg);
					}
				}
			}
		} else {
			synchronized (handlerPool) {
				Handler h = handlerPool.get(receiver);
				if (h != null) {
					h.out.writeObject(msg);
				}
			}
		}
	}

	public void notify2() throws Exception {
		synchronized (handlerPool) {
			HashMap<String, Boolean> hasLoginMap = new HashMap<>();
			hasLoginMap.put("all", true);
			for (Entry<String, Handler> entry : handlerPool.entrySet()) {
				if (entry.getValue() == null) {
					hasLoginMap.put(entry.getKey(), false);
				} else {
					hasLoginMap.put(entry.getKey(), true);
				}
			}
			MsgPackage msg = new MsgPackage(Operation.NOTIFY, null, null, null, null, hasLoginMap);
			for (Entry<String, Handler> entry : handlerPool.entrySet()) {
				if (entry.getValue() != null) {
					entry.getValue().out.writeObject(msg);
				}
			}
		}

	}
}